<?php

namespace App\Http\Controllers;

use ActionLog;
use App\Http\Traits\UserPrivilege;
use App\Http\Traits\Utils;
use App\Models\SyUser;
use App\Models\Userinfo;
use App\Models\WxUser;
use Bouncer;
use DefaultCompany;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use JWTAuth;
use DB;

class AuthController extends Controller
{

    use UserPrivilege, Utils;

    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login', 'sendCode', 'forgetPassword', 'bindLogin', 'bindToken']]);
    }

    /**
     * @apiSampleRequest http://app57.test/auth/login/
     * @api {post} /auth/login/ 登录
     * @apiDescription 用户登录
     * @apiGroup 授权
     * @apiPermission none
     * @apiParam {String} username 用户名
     * @apiParam {String} password 用户密码
     * @apiSuccess {String} access_token 用户唯一登录标识
     * @apiSuccess {String} token_type 类型
     * @apiSuccess {Number} expires_in 有效时间(秒)
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "routes": [],
     *          "user": {},
     *          "ability": []
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function login(Request $request)
    {
        $post = $request->input();
        $credentials = $this->getCredentials($post);
        $token = $this->auth()->attempt($credentials);
        if (!$token) {
            return $this->error('账号或密码错误');
        }
        ActionLog::createActionLog('login', '登录成功');

        $users = $this->auth()->user()->load('area.children')->toArray();

        $areas = $this->getDefaultArea($users);

        return $this->respondWithToken($token, "登录成功", $areas);
    }

    //绑定用户
    public function bindLogin(Request $request)
    {
        $post = $request->input();
        $credentials = $this->getCredentials($post);
        $token = $this->auth()->attempt($credentials);
        if (!$token) {
            return $this->error('账号或密码错误');
        }
        $openid = $request->input('openid');
        $user = $this->auth()->user();
        $userId = $user->userid;
        $wxuser = WxUser::where('openid', $openid)->where('user_id', $userId)->first();
        if (!$wxuser) {
            Bouncer::assign(config('auth.roles.admin'))->to($user);
            WxUser::where('openid', $openid)->update([
                'user_id' => $userId,
            ]);
        }

        ActionLog::createActionLog('login', '绑定成功');
        return $this->respondWithToken($token, "绑定成功");
    }

    //根据绑定用户登录
    public function bindToken(Request $request)
    {
        $openid = $request->input('openid');
        $user = WxUser::where('openid', $openid)->first();
        if (!$user) {
            return $this->error('');
        }
        if ($user->status == 0) {
            return $this->error(['data' => ['message' => '请先关注微信公众号!', 'err' => -1]]);
        }
        if (!$user->user_id) {
            return $this->error(''); // 没绑定用户
        }
        $token = JWTAuth::fromUser(SyUser::find($user->user_id));
        ActionLog::createActionLog('login', '登录成功');
        return $this->respondWithToken($token, "");
    }

    //获取用户登录信息
    protected function getCredentials($post)
    {
        $credentials = [
            'username' => $post['username'],
            'password' => $post['password'],
        ];
        return $credentials;
    }

    /**
     * @apiSampleRequest http://app57.test/auth/userinfo
     * @api {get} /auth/userinfo 用户信息
     * @apiHeader {String} authorization  用户访问标识
     * @apiDescription 获取用户信息
     * @apiGroup 授权
     * @apiPermission none
     * @apiSuccess {Object[]} routes 路由
     * @apiSuccess {Object} user 路由
     * @apiSuccess {Object} ability 路由
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "routes": [],
     *          "user": {},
     *          "ability": []
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function getUserInfo(Request $request)
    {
        $openid = $request->input('openid');
        $this->judgeWechat($openid);
        $userModel = $this->user();

        $userModel->load('company');
        $userModel->load('area.children');
//        Bouncer::scope()->onlyRelations();


        Bouncer::scope()->to(null);
        $isSuper = $this->isSuper($userModel);
        $isAdmin = $userModel->isSuperAdmin();

        $user = $userModel->toArray();

       // $user['area'] = [];

        $user['roles'] = $userModel->roles()->get()->pluck('name');
        $query = \App\Models\Menu::query();
        $ability = [];

        if (!$isSuper) {
            $ability = $userModel->getAbilities()->pluck('name')->toArray();
            $query->whereIn('pri', $ability)->orWhere('pri', '=', '*');
        }

        $lists = $query
            ->select([
                'route_name as name',
                'route_path as path',
                'component',
                'redirect',
                'meta',
                'pid',
                'id',
                'hidden',
                'buttons',
                'always_show',
                'icon',
                'sort_order',
                'link_dpt_id',
                'link_field',
                'props',
                'menu_type',
                'name as menu_name',
                'menu_group'])
            ->get()
            ->toArray();

        foreach ($lists as &$item) {
            $item['always_show'] = (bool) $item['always_show'];
            $item['hidden'] = (bool) $item['hidden'];
            // if ($item['name'] == '*') {
            //     unset($item['name']);
            // }
        }
        unset($item);

        $routes = $this->listToTree($lists);

       // dd($user);
        //var_dump($routes);
        $warnNum = \App\Models\Phpwarn::count();

        $user['notification'] = $warnNum;

        if (!$user['company']) {
            $company = array_only((array) DefaultCompany::getCompanyCache(), ['Co_ID', 'Co_Name']);
            $user['company'] = $company;
        }

        
        $user['area'] = $this->getDefaultArea($user);

        $areaDevicesTree = app('App\Models\Area')->getAreaDevices(array_get($user, 'scope'));

       

        // $areaDevicesTree = [];
        return compact('routes', 'user', 'ability', 'areaDevicesTree');
    }

    //默认区域
    protected function getDefaultArea($user) {
        $defaultArea = [];
        if (!$user['area']) {
            $defaultArea = array_only((array) DefaultCompany::getAreaCache(), ['AreaId', 'AreaName', 'area_text']);
            return $defaultArea;
        }
 
        $area = data_get($user, 'area.children');
        if($area) {
            return $area[0];
        }
        return data_get($user, 'area', []);
        
    }

    //微信判断
    protected function judgeWechat($openid)
    {
        if (!$openid) {
            return;
        }
        $wxuser = WxUser::where('openid', $openid)->first();
        if (!$wxuser) {
            return $this->error(''); //用户不存在
        }
        if ($wxuser->status == 0) {
            return $this->error(['data' => ['message' => '请先关注微信公众号!', 'err' => -1]]); //没关注微信
        }
        if (!$wxuser->user_id) {
            return $this->error(''); //没绑定用户
        }
    }

    /**
     * @apiSampleRequest http://app57.test/auth/logout/
     * @api {post} /auth/logout/ 退出
     * @apiHeader {String} authorization  用户访问标识
     * @apiDescription 用户退出登录
     * @apiGroup 授权
     * @apiPermission none
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "message": "",
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function logout()
    {
        ActionLog::createActionLog('loginout', '退出成功');
        $this->auth()->logout();
    }

    /**
     * @apiSampleRequest http://app57.test/auth/refresh/
     * @api {post} /auth/refresh/ 刷新
     * @apiHeader {String} authorization  用户访问标识.
     * @apiDescription 刷新token
     * @apiGroup 授权
     * @apiPermission none
     * @apiSuccess {String} access_token 用户唯一登录标识
     * @apiSuccess {String} token_type 类型
     * @apiSuccess {Number} expires_in 有效时间(秒)
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "message": "",
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function refresh()
    {
        return $this->respondWithToken($this->auth()->refresh());
    }

    //返回格式化token
    protected function respondWithToken($token, $msg = "", $data=[])
    {
        $result = [
            'access_token' => $token,
            'token_type' => 'Bearer',
            'expires_in' => $this->auth()->factory()->getTTL() * 60,
            'message' => $msg,
        ];

        if($data) {
            $result['info'] = $data;
        }

        return $result;
    }

    /**
     * @apiSampleRequest http://app57.test/auth/userinfo
     * @api {put} /auth/userinfo 更新用户信息
     * @apiHeader {String} authorization  用户访问标识.
     * @apiError (错误代码) code -1=错误
     * @apiDescription 更新用户信息
     * @apiGroup 授权
     * @apiPermission none
     * @apiParam {File} avatar 头像路径
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "message": "",
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function saveUserInfo(Request $request)
    {
        $user = $this->user();
        $avatar = $request->input('logo', '');
        $user->avatar = $avatar;
        if (!$user->save()) {
            $this->error('个人信息修改失败');
        }
    }

    /**
     * @api {post} /auth/password 更改密码
     * @apiDescription 更改密码
     * @apiGroup 授权
     * @apiPermission none
     * @apiParam {String} password 原始密码
     * @apiParam {String} new_password 新密码
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "message": "",
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function modifyPassword(Request $request)
    {
        $user = $this->user();
        $this->validate($request, [
            'password' => 'required|min:6',
            'new_password' => 'required|min:6|confirmed',
        ]);

        $password = $request->input('password');
        $newPassword = $request->input('new_password');

        if (!$this->checkPwd($password, $user->userpwd)) {
            return $this->error('原密码不正确');
        }

        $user->userpwd = $newPassword;
        if (!$user->save()) {
            $this->error('密码修改失败');
        }
        // token失效
        JWTAuth::parseToken()->invalidate();
    }

    //验证密码是否相等
    protected function checkPwd($password, $srcPassword)
    {
        return md5(trim($password)) === $srcPassword;
    }

    //发送短信
    protected function sendSms($phone, $code)
    {
        $invoice = [
            'phone' => $phone,
            'content' => '您好,当前验证码是' . $code,
        ];
        // $when = \Carbon\Carbon::now()->addMinutes(1);
        // $ret = Notification::send($phone, (new \App\Notifications\Phone($invoice))->delay($when));
        $request = app('request')->user();
        \App\Models\SmsSend::create([
            'Co_ID' => $request ? $request->Co_ID : null,
            'phone' => $invoice['phone'],
            'msg' => $invoice['content'],
            'sendtime' => date('YmdHi'),
        ]);
        return true;
    }

    //生成验证码
    protected function getVerifyCode($len = 6)
    {
        $start = str_pad(1, $len, 0);
        $end = str_pad(9, $len, 9);
        return mt_rand($start, $end);
    }

    /**
     * @api {post} /auth/sendcode/ 发送验证码
     * @apiDescription 发送验证码
     * @apiGroup 授权
     * @apiPermission none
     * @apiParam {Number} phone 用户手机号
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "message": "",
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function sendCode(Request $request)
    {
        $this->validate($request, [
            'phone' => ['required', 'digits:11', config("site.phone")],
        ]);
        $phone = $request->input('phone');
        $userinfo = Userinfo::where('userphone', '=', trim($phone))->first();
        if (!$userinfo) {
            return $this->error('手机号不存在');
        }
        $code = $this->getVerifyCode();
        $ret = $this->sendSms($phone, $code);
        if (!$ret) {
            $this->error('发送短信失败');
        }
        // 发送成功, 设置缓存
        Cache::put('code:' . $phone, $code, config('auth.code_expire'));
    }

    //检查验证码是否过期
    protected function checkCodeExpire($phone)
    {
        return Cache::get('code:' . $phone);
    }

    //检查验证码是否相等
    protected function checkCodeEqual($phone, $code)
    {
        return Cache::get('code:' . $phone) == $code;
    }

    /**
     * @api {post} /auth/forgetpassword/ 忘记密码
     * @apiDescription 忘记密码
     * @apiGroup 授权
     * @apiPermission none
     * @apiParam {Number} phone 用户手机号
     * @apiParam {Number} code 短信验证码
     * @apiParam {String} password 新密码
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "message": "",
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function forgetPassword(Request $request)
    {
        $user = $this->user();
        if ($user) {
            JWTAuth::parseToken()->invalidate();
        }
        $this->validate($request, [
            'phone' => ['required', 'digits:11', config("site.phone")],
            'code' => 'required|min:6',
            'password' => 'required|min:6',
        ]);
        $code = $request->input('code');
        $phone = $request->input('phone');
        if (!$this->checkCodeExpire($phone)) {
            return $this->error('验证码已过期');
        }
        if (!$this->checkCodeEqual($phone, $code)) {
            return $this->error('验证码输入错误');
        }
        $userinfo = Userinfo::where('userphone', '=', trim($phone))->first();
        if (!$userinfo) {
            return $this->error('手机号不存在');
        }
        $muser = $userinfo->user;
        $password = $request->input('password');
        $muser->userpwd = $password;
        if (!$muser->save()) {
            $this->error('找回密码失败');
        }
    }

    /**
     * @api {post} /auth/authcode/ 授权码操作
     * @apiDescription 授权码操作
     * @apiGroup 授权
     * @apiPermission none
     * @apiParam {String} authcode 授权码
     * @apiSuccessExample {json} 成功:
     *     HTTP/1.1 201
     *     {
     *         "code": 0,
     *         "message": "",
     *
     *     }
     * @apiErrorExample {json} 失败:
     *     HTTP/1.1 422
     *     {
     *       "code": -1,
     *       "message": "错误提示"
     *     }
     */
    public function authcode(Request $request)
    {
        //时间获取
        $lifeInfo = DB::table('t_microdog')->select(['dt_limitdate'])->first();



        $this->validate($request, [
            'authcode' => 'sometimes|required',
        ]);

        $authcode = $request->input('authcode');
        
        //更新授权码
        if($authcode) {
            DB::table('t_soft_dog_info')->update([ 'soft_dog_sn'=>$authcode ]);
        }

        $lifetime = $lifeInfo->dt_limitdate;

        $status = true;
        if(time()>strtotime($lifetime)) {
            $status = false;
        }

        $dogInfo = DB::table('t_soft_dog_info')->first();

        return [ 'lifetime'=>$lifetime, 'running_status'=> $status, 'dog_info'=>$dogInfo ];
        
    }

}
